<style lang="scss">
.ua-fileup-viewer {
  // 上传列表的容器
  &--container {
    position: fixed;
    top: 0;
    right: 0;
    max-height: 100vh;
    display: flex;
    flex-direction: column;
    padding-left: 10px;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: none;
    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }
  }
  &--card {
    flex-shrink: 0;
    display: inline-block;
    position: relative;
    right: 0;
    overflow: hidden;
    box-shadow: 0 0 5px 1px #999;
    line-height: 1;
    transition: height 0.5s ease, opacity 0.5s ease, transform 0.5s ease;
    border-radius: 5px;
    margin: 15px 15px 0 0;
    height: 0;
    transform: translate3d(150%, 0, 0);
    opacity: 0;
    &.underway {
      height: auto;
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }
  &--header {
    font-size: 14px;
    font-weight: bold;
    padding: 15px 15px 5px;
  }
  &--progress {
    display: flex;
    width: auto;
    align-content: center;
    padding: 10px 15px;
    min-width: 200px;
    &-scrollbar {
      height: 12px;
      background-color: #999;
      transition: height 0.5s ease 0.2s, opacity 0.3s ease 0.3s;
      position: relative;
      overflow: hidden;
      flex-grow: 1;
    }
    &-thumb {
      position: absolute;
      top: 0;
      left: -100%;
      width: 100%;
      height: 100%;
      background-color: pink;
    }
    &-percent {
      width: 40px;
      font-size: 12px;
      flex-shrink: 0;
      text-align: right;
    }
  }
  &--status {
    padding: 10px 15px;
    display: flex;
    max-width: 400px;
    &-icon {
      flex-shrink: 0;
      width: 20px;
      font-size: 16px;
    }
    &-message {
      flex-grow: 1;
    }
  }
  &--footer {
    padding: 0 15px 5px;
    text-align: right;
  }
}
</style>

<template>
  <teleport :to="selector">
    <div class="ua-fileup-viewer--card" :class="form.position">
      <div class="ua-fileup-viewer--header" v-show="form.visible">{{ form.title }}</div>
      <div v-show="form.type === 'underway'" class="ua-fileup-viewer--progress">
        <div class="ua-fileup-viewer--progress-scrollbar">
          <div
            class="ua-fileup-viewer--progress-thumb"
            :style="{
              transform: `translate3d(${form.percent}%, 0, 0)`,
            }"
          />
        </div>
        <div class="ua-fileup-viewer--progress-percent">{{ form.percent }}%</div>
      </div>
      <div
        class="ua-fileup-viewer--status"
        v-show="form.visible && form.type && form.type !== 'underway'"
      >
        <div class="ua-fileup-viewer--status-icon">
          <UIconfont :name="form.type" />
        </div>
        <div class="ua-fileup-viewer--status-message">{{ form.message }}</div>
      </div>
      <div class="ua-fileup-viewer--footer" v-show="form.visible">
        <el-button type="text" style="color: red" @click="onCancel">取消</el-button>
        <el-button type="text" @click="onHide">隐藏</el-button>
      </div>
    </div>
  </teleport>
</template>

<script lang="ts">
import { qiniuUploadCallback } from '@assets/utils/qiniu'
import { defineComponent, onUnmounted, reactive, watch } from 'vue'
import UIconfont from './UIconfont.vue'

export default defineComponent({
  name: 'UFileUpViewer',
  props: {
    file: File,
    timeout: {
      type: Number,
      default: 1500,
    },
  },
  setup(props) {
    const selector = initialize()
    const form = reactive({
      visible: false,
      title: 'xxxxxxxxxxxxxx.png',
      percent: 0,
      cancel: null as null | Function,
      message: '',
      type: '' as '' | 'underway' | 'success' | 'error' | 'waring', // 无，上传中，成功，失败，取消
      position: '' as '' | 'underway',
    })

    watch(
      () => form.type,
      (nv) => {
        if (nv === 'underway') {
          form.visible = true
          setTimeout(() => {
            form.position = 'underway'
          }, props.timeout)
          return
        }
        if (nv === 'success') {
          form.message = '上传成功！！！'
        }
        if (nv === 'waring') {
          form.message = '取消上传！！！'
        }
        setTimeout(() => {
          form.position = ''
        }, props.timeout)
      }
    )

    watch(
      () => props.file,
      (nv, ov) => {
        form.type = 'underway'
        if (nv instanceof File) {
          qiniuUploadCallback(nv, {
            initialize: (key: string, cancel: Function) => {
              form.title = key
              form.cancel = cancel
              form.type = 'underway'
            },
            percent: (percent: number) => {
              form.percent = percent
              if (percent === 100) {
                form.type = 'success'
              } else {
                form.type = 'underway'
              }
            },
            error: (error) => {
              form.type = 'error'
              form.message = error.message
            },
          })
        }
      },
      { immediate: true }
    )

    function onCancel() {
      if (form.type !== 'underway') return
      form.type = 'waring'
      if (form.cancel) {
        form.cancel()
      }
    }

    function onHide() {
      form.visible = false
    }

    onUnmounted(() => {
      if (props.file instanceof File) {
        qiniuUploadCallback(props.file)
      }
    })

    return { selector, form, onCancel, onHide }
  },
  components: { UIconfont },
})

function initialize() {
  const selector = '.ua-fileup-viewer--container'
  let div: null | HTMLDivElement = document.querySelector(selector)
  if (!div) {
    div = document.createElement('div')
    div.classList.add(selector.slice(1))
    document.body.append(div)
  }
  return selector
}
</script>
